/******************************************************************************
 *      Mestrado em Ciência da Computação - UFMS
 *		Redes de Computadores - Prof. Dr. Ronaldo Alves Ferreira
 *		Alunos: Geraldo Landre, Marcel Tolentino, Vinícius Bueno
 *****************************************************************************/

#include "vstring.h"

vstring* new_vstring()
{
    vstring *v = (vstring *) malloc(sizeof(vstring));
    v->mem_size = 0;
    v->length = 0;
    v->pt = NULL;

    return v;
}

int realloc_string(vstring **v,int size)
{
    //printf("size no realloc - %i\n",size);
    if(size > 0)
    {
        if(*v == NULL)
            *v = new_vstring();
        (*v)->pt = (char *) realloc((*v)->pt,(size + 1) * sizeof(char));
        if((*v)->pt != NULL)
        {
            (*v)->mem_size = size;
            (*v)->pt[size] = '\0';
        }
        else
        {
            free(*v);
            *v = NULL;
        }
        return 1;
    }
    free_string(v);
    return 0;
}

int alloc_string(vstring **v,int size)
{
    int i;
    if(realloc_string(v,size))
    {
        for(i = 0; i <= size; i++)
            (*v)->pt[i] = '\0';
        (*v)->length = 0;
        return 1;
    }
    return 0;
}

int free_string(vstring **v)
{
    if(*v != NULL)
    {
        if((*v)->pt != NULL)
            (*v)->pt = realloc((*v)->pt,0);
        *v = NULL;
    }
    return 1;
}

int is_null(vstring **v)
{
    if((*v) == NULL || (*v)->pt == NULL || (*v)->length == 0)
    {
        free_string(v);
        return 1;
    }
    return 0;
}

void print_string(vstring *v)
{
    if(!is_null(&v))
        printf("%s\n",v->pt);
    else
        printf("vstring nula\n");
}

void print_vstring(vstring *v)
{
    if(v != NULL)
    {
        printf("tamanho: %i\tmemória: %i\n\n",v->length,v->mem_size);
        print_string(v);
        printf("\n\n");
    }
    else
        printf("vstring nula\n\n");
}

int get_more_space(vstring **v,unsigned new_size)
{
    int i;

    if(*v == NULL)
        *v = new_vstring();

    if((*v)->mem_size < new_size)
    {
        (*v)->pt = (char *) realloc((*v)->pt,(new_size + 1) * sizeof(char));
        for(i = (*v)->length; i < new_size; i++)
            (*v)->pt[i] = '\0';
        (*v)->mem_size = new_size;

        return 1;
    }
    return 0;
}

int copy_string(vstring **v,char *orig)
{
    if(*v == NULL)
        *v = new_vstring();

    int size = strlen(orig);

    if((*v)->mem_size < size)
        get_more_space(v,size);
    memcpy((*v)->pt,orig,size);
    (*v)->pt[size] = '\0';
    (*v)->length = size;

    return 1;
}

int copy_vstring(vstring **copy,vstring *orig)
{
    if(orig !=  NULL)
    {
        if(*copy == NULL)
            *copy = new_vstring();

        if(alloc_string(copy,orig->length))
        {
            memcpy((*copy)->pt,orig->pt,orig->length);
            (*copy)->length = orig->length;
            (*copy)->pt[(*copy)->length] = '\0';

            return 1;
        }
        return 0;
    }
    free_string(copy);

    return 1;
}

int copy_substring(vstring **copy,vstring *orig,int start,int size)
{
    if(*copy == NULL)
        *copy = new_vstring();

    if(alloc_string(copy,size))
    {
        memcpy((*copy)->pt,orig->pt + start,size);
        (*copy)->length = size;
        (*copy)->pt[(*copy)->length] = '\0';

        return 1;
    }
    return 0;
}

int concat_string(vstring **pre,char *suf)
{
    if(*pre == NULL)
        *pre = new_vstring();

    if(get_more_space(pre,(*pre)->length + strlen(suf)))
    {
        memcpy((*pre)->pt + (*pre)->length,suf,strlen(suf));
        (*pre)->length += strlen(suf);
        (*pre)->pt[(*pre)->length] = '\0';

        return 1;
    }
    return 0;
}

int concat_vstring(vstring **pre,vstring *suf)
{
    if(*pre == NULL)
        *pre = new_vstring();

    if(get_more_space(pre,(*pre)->length + suf->length))
    {
        memcpy((*pre)->pt + (*pre)->length,suf->pt,suf->length);
        (*pre)->length += suf->length;
        (*pre)->pt[(*pre)->length] = '\0';

        return 1;
    }
    return 0;
}

int get_index_occour(vstring **v,char *occour)
{
    char *aux = NULL;
    if(!is_null(v))
        if((aux = strstr((*v)->pt,occour)) != NULL)
            return aux - (*v)->pt;
    return -1;
}

void remove_substring(vstring **v,int start,int size)
{
    int finish = size;
    for(finish += start;finish < (*v)->length; start++, finish++)
        (*v)->pt[start] = (*v)->pt[finish];
    (*v)->pt[start] = '\0';
    (*v)->length -= size;
    realloc_string(v,(*v)->length);
}

void insert_substring(vstring **v,int start,int size)
{
    int new_end,old_end,i = start;

    if((*v)->length + size > (*v)->mem_size)
        realloc_string(v,(*v)->length + size);

    for(new_end = (*v)->mem_size,old_end = (*v)->length; old_end >= start; new_end--,old_end--)
        (*v)->pt[new_end] = (*v)->pt[old_end];
    (*v)->length += size;

    for(;start >= i; start--)
        (*v)->pt[start] = ' ';
}

void trim(vstring **v)
{
    int i;
    if(*v != NULL)
    {
        for(i = 0; (*v)->pt[i] == ' '; i++);
        if(i > 0)
            remove_substring(v,0,i);
        for(i = (*v)->length; i > 0 && (*v)->pt[i - 1] == ' '; i--);
        if(i < (*v)->length)
            realloc_string(v,i);
    }
}

int get_token(vstring **orig,vstring **tk,char *delimiter)
{
    int index = -1;

    if(!is_null(orig))
    {
        if((index = get_index_occour(orig,delimiter)) >= 0)
        {
            copy_substring(tk,*orig,0,index);
            remove_substring(orig,0,index + strlen(delimiter));
        }
        else
        {
            remove_all(orig,CR);
            remove_all(orig,END_LINE);
            if(!is_null(orig))
                copy_substring(tk,*orig,0,(*orig)->length);
            free_string(orig);
        }
        remove_all(tk,CR);
        remove_all(tk,END_LINE);
        trim(tk);

        return 1;
    }
    else
        free_string(tk);
    return 0;
}

int remove_occour(vstring **v,char *occour)
{
    int index = -1;
    if((index = get_index_occour(v,occour)) >= 0)
    {
        remove_substring(v,index,strlen(occour));
        return 1;
    }
    return 0;
}

int remove_all(vstring **v,char *occour)
{
    while(remove_occour(v,occour));
    return 1;
}

int replace_occour(vstring **v,char *old_occ,char *new_occ)
{
    int i,j,k;
    char *occour = NULL;

    if(strlen(old_occ) > 0 && (occour = strstr((*v)->pt,old_occ)) != NULL)
    {
        i = k = occour - (*v)->pt;
        if(strlen(new_occ) > strlen(old_occ))
        {
            insert_substring(v,occour - (*v)->pt,(strlen(new_occ) - strlen(old_occ)));

            for(j = 0; i < k + strlen(new_occ); i++,j++)
                (*v)->pt[i] = new_occ[j];
        }
        else
        {
            for(j = 0; i < k + strlen(new_occ); i++,j++)
                (*v)->pt[i] = new_occ[j];
            if((strlen(old_occ) - strlen(new_occ)) > 0)
                remove_substring(v,i,(strlen(old_occ) - strlen(new_occ)));
        }
        return 1;
    }
    return 0;
}

int replace_all(vstring **v,char *old_occ,char *new_occ)
{
    int i;
    for(i = 0;replace_occour(v,old_occ,new_occ);i++);
    return i;
}

void invert_string(vstring** v)
{
    int i = 0,j = (*v)->length - 1;
    char c;
    
    while(i <= j)
    {
        c = (*v)->pt[i];
        (*v)->pt[i] = (*v)->pt[j];
        (*v)->pt[j] = c;
        i++;
        j--;
    }    
}